home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_2 / asc2bin.c < prev    next >
Text File  |  1995-03-31  |  11KB  |  442 lines

  1. Article 4494 of comp.sys.handhelds:
  2. Path: en.ecn.purdue.edu!noose.ecn.purdue.edu!samsung!usc!zaphod.mps.ohio-state.edu!ub!acsu.buffalo.edu
  3. From: cloos@acsu.buffalo.edu (James H. Cloos)
  4. Newsgroups: comp.sys.handhelds
  5. Subject: Asc2bin and Bin2asc, too.
  6. Message-ID: <61295@eerie.acsu.Buffalo.EDU>
  7. Date: 22 Feb 91 19:49:45 GMT
  8. Sender: news@acsu.Buffalo.EDU
  9. Organization: State University of New York @ Buffalo
  10. Lines: 427
  11. Nntp-Posting-Host: hemingway.acsu.buffalo.edu
  12.  
  13. Please find below a slightly improved version of asc2bin.c; its improvement
  14. is the ability to create an ASC format file from a hp48sx binary file.  To
  15. use it, compile with "cc -g -o asc2bin asc2bin.c" and then, if you machine
  16. is capable of multiple links (all Unix, I understand Amigas, usw.), then
  17. link asc2bin to bin2asc.  If not, just copy asc2bin to bin2asc.  The
  18. program checks the command name at execution time and chooses which way to
  19. convert from that.  (The next improvement would be to make that decission
  20. based on the file's type.  Perhaps if it starts with HPHP48- then use
  21. bin2asc option, else use asc2bin option.  Maybe I'll even get around to
  22. that sometime [SIGH]....)
  23.  
  24. I've checked the output of bin2asc vs. hyde.lib, chip225 & its games, and a
  25. few short things I could type in off the 48's screen and into the Sun.  (I
  26. can't use ckermit between the workstations and the 48 just now as I get
  27. /usr/spool/locks: permission denied errors; w/ luck that could change in
  28. the future.)    **{Excuse the wordiness, bitte.}**
  29.  
  30. Here is the src:
  31.  
  32. /*==-==--==---==----==-----==------==------==-----==----==---==--==-==*
  33.  *                       START OF asc2bin.c                           *
  34.  *--=--==--===--====--=====--======--======--=====--====--===--==--=--*/
  35.  
  36. /* 
  37.     This programs reads an up to 127K ASCII (RPL) file consisting of a
  38.     string intended for ASC-> and converts it into a binary object file.
  39.  
  40.     This program was compiled with Microsoft C 5.1 and Turbo C. ANSI C
  41.     conventions are mostly followed.
  42.  
  43.     The original algorithm for CRC computation was extracted from
  44.     Li Sheng's posting to comp.sys.handhelds.
  45.  
  46.     01/19/91 PMW  created
  47.     02/14/91 MAdler     modified for portability
  48.     15.02.91 JimC added in bin2asc option
  49. */
  50.  
  51. #include <stdio.h>
  52. #include <errno.h>
  53.  
  54.  
  55. #ifdef __STDC__
  56. #  define MODERN
  57. #endif
  58.  
  59. #ifdef __TURBOC__
  60. #  ifndef MODERN
  61. #    define MODERN
  62. #  endif
  63. #endif
  64.  
  65. #ifdef MODERN
  66. #  include <stdlib.h>
  67. #  include <string.h>
  68. #  include <ctype.h>
  69. #  define FOPR "rb"
  70. #  define FOPW "wb"
  71. #else
  72. #  define void int
  73. #  define size_t unsigned int
  74.    extern char *strcat();
  75.    extern char *strcpy();
  76. #  define FOPR "r"
  77. #  define FOPW "w"
  78. #endif
  79.  
  80.  
  81. typedef unsigned char BYTE;
  82. typedef unsigned int WORD;
  83.  
  84.  
  85. /* Function prototypes for ANSI C */
  86. #ifdef MODERN
  87.   int FileExists(char *);
  88.   long FileSize(FILE *);
  89.   WORD crcBlock(BYTE *, size_t);
  90.   void CopyLine(BYTE **, char **, WORD *);
  91.   void ReadFile(char *, BYTE **, WORD *);
  92.   void WriteFile(char *, BYTE *, WORD );
  93.   int main(int,  char **);
  94. #endif
  95.  
  96. #define HEADER_STRING "HPHP48-C"
  97.         /* My own version */
  98.  
  99. #define MAX_READ_SIZE 127
  100.  
  101. #ifndef FILENAME_MAX
  102. #  define FILENAME_MAX 65
  103. #endif
  104.  
  105. #ifndef EXIT_FAILURE
  106. #  define EXIT_FAILURE 1
  107. #endif
  108.  
  109. #ifndef EXIT_SUCCESS
  110. #  define EXIT_SUCCESS 0
  111. #endif
  112.  
  113. #ifndef SEEK_SET
  114. #  define SEEK_SET 0
  115. #endif
  116.  
  117. #ifndef SEEK_END
  118. #  define SEEK_END 2
  119. #endif
  120.  
  121. #ifndef isxdigit
  122. #  define isxdigit(c) (c >= '0' && c <= '9' || c >= 'A' && c <= 'F')
  123. #endif
  124. #define HEX2INT(hc) ((unsigned int) (isdigit(hc) ? (hc)-'0' : (hc)-'A'+10))
  125.  
  126. int FileExists(f)
  127. char *f;
  128. {
  129.     FILE *tf;
  130.  
  131.     if ((tf = fopen(f, FOPR)) != NULL) {
  132.         fclose(tf);
  133.         return 1;
  134.     }
  135.     else
  136.         return 0;
  137. }
  138.  
  139. long FileSize(f)
  140. FILE *f;
  141. {
  142.     long origPos = ftell(f), fileSize = 0;
  143.  
  144.     fseek(f, 0L, SEEK_END);
  145.     fileSize = ftell(f);
  146.     fseek(f, origPos, SEEK_SET);
  147.  
  148.     return fileSize;
  149. }
  150.  
  151.  
  152. #define CALC_CRC(c, i) (((((c)^(i)) & 0xF) * 0x1081) ^ ((c) >> 4))
  153. WORD crcBlock(mb, len)
  154. BYTE *mb;
  155. size_t len;
  156. {
  157.     WORD crc = 0, bObjSize = len/2;
  158.  
  159.     while (bObjSize--) {
  160.         crc = CALC_CRC(crc, (WORD) (*mb) & 0xF);
  161.         crc = CALC_CRC(crc, (WORD) ((*mb) >> 4));
  162.         ++mb;
  163.     }
  164.     if (len & 1)
  165.         crc = CALC_CRC(crc, (WORD) (*mb) & 0xF);
  166.  
  167.     return crc;
  168. }
  169.  
  170.  
  171. void CopyLine(mb, s, objSize)
  172. BYTE **mb;
  173. char **s;
  174. WORD *objSize;
  175. {
  176.     char *ts = *s;
  177.     BYTE *tmb = *mb;
  178.     WORD ls = 0;
  179.  
  180.     while (isxdigit(ts[0]) && isxdigit(ts[1])) {
  181.         *tmb++ = (BYTE) (HEX2INT(ts[0]) + (HEX2INT(ts[1]) << 4));
  182.         ls += 2;
  183.         ts += 2;
  184.     }
  185.  
  186.     if (isxdigit(ts[0]) && ts[1] == '"') {
  187.         /* we ended on a nibble boundary!! */
  188.         BYTE crc1, crc2;
  189.  
  190.         /* correct crc by nibble shifting end */
  191.         crc2 = (BYTE) ((tmb[-1] >> 4) + (HEX2INT(ts[0]) << 4));
  192.         crc1 = (BYTE) ((tmb[-2] >> 4) + ((tmb[-1] & 0xF) << 4));
  193.  
  194.         /* fix memory buffer */
  195.         tmb[-2] &= 0xf;
  196.         tmb[-1] = crc1;
  197.         *tmb++ = crc2;
  198.         ++ls;
  199.         ++ts;
  200.     }
  201.  
  202.     *s = ts;
  203.     *mb = tmb;
  204.     *objSize += ls;
  205. }
  206.  
  207.  
  208. #define READLN(s, f) fgets((s), sizeof(s), (f))
  209.  
  210. void ReadFile(filepath, mb, objSize)
  211. char *filepath;
  212. BYTE **mb;
  213. WORD *objSize;
  214. {
  215.     FILE *infile;
  216.     char lineBuf[250], *p;
  217.     WORD bufSize;
  218.     long fileSize;
  219.     BYTE *wmb;
  220.  
  221.     if (!strchr(filepath, '.'))
  222.         strcat(filepath, ".ASC");
  223.  
  224.     if (!(infile = fopen(filepath, "r"))) {
  225.         fprintf(stderr, "asc2bin:  can't open %s\n", filepath);
  226.         exit(EXIT_FAILURE);
  227.     }
  228.  
  229.     fileSize = FileSize(infile);
  230.     if (fileSize > MAX_READ_SIZE*1024L) {
  231.         fprintf(stderr, "asc2bin: File %s is too long\n", filepath);
  232.         exit(EXIT_FAILURE);
  233.     }
  234.     bufSize = 4+(WORD) (fileSize / 2);  /* approximate byte size of object */
  235.     if (!(*mb = (BYTE *) malloc(bufSize))) {
  236.         fprintf(stderr, "asc2bin:  Unable to allocate %u bytes\n", bufSize);
  237.         exit(EXIT_FAILURE);
  238.     }
  239.     wmb = *mb;
  240.  
  241.     /* find string */
  242.     while (!feof(infile)) {
  243.         if (!READLN(lineBuf, infile)) {
  244.             if (feof(infile))
  245.                 fputs("asc2bin:  Unable to locate string\n", stderr);
  246.             else
  247.                 perror("asc2bin:  Read error");
  248.  
  249.             fclose(infile);
  250.             exit(EXIT_FAILURE);
  251.         }
  252.  
  253.         if (*lineBuf == '"')
  254.             break;
  255.     }
  256.  
  257.     *objSize = 0;
  258.  
  259.     /* put string into buffer */
  260.     p = &lineBuf[1];  /* skip opening quote */
  261.     CopyLine(&wmb, &p, objSize);
  262.  
  263.     /* copy remainder into buffer */
  264.     while (*p != '"' && !feof(infile)) {
  265.         if (!READLN(lineBuf, infile)) {
  266.             if (feof(infile))
  267.                 fputs("asc2bin:  Unable to locate closing quote\n", stderr);
  268.             else
  269.                 perror("asc2bin:  Read error");
  270.  
  271.             fclose(infile);
  272.             exit(EXIT_FAILURE);
  273.         }
  274.  
  275.         p = lineBuf;
  276.         CopyLine(&wmb, &p, objSize);
  277.     }
  278.  
  279.     fclose(infile);
  280. }
  281.  
  282. void WriteFile(filepath, mb, objSize)
  283. char *filepath;
  284. BYTE *mb;
  285. WORD objSize;
  286. {
  287.     FILE *outfile;
  288.     char *extpos = strchr(filepath, '.');
  289.  
  290.     strcpy(extpos+1, "bin");
  291.  
  292.     if (FileExists(filepath)) {
  293.         fprintf(stderr, "asc2bin:  file already exists: %s\n", filepath);
  294.         exit(EXIT_FAILURE);
  295.     }
  296.  
  297.     if (!(outfile = fopen(filepath, FOPW))) {
  298.         fprintf(stderr, "asc2bin:  unable to create %s\n", filepath);
  299.         exit(EXIT_FAILURE);
  300.     }
  301.  
  302.     fputs(HEADER_STRING, outfile);
  303.     while (objSize--)
  304.         fputc(*mb++, outfile);
  305.  
  306.     fclose(outfile);
  307. }
  308.  
  309. int TransBinFile(InFileName, OutFileName)
  310. char *InFileName, *OutFileName;
  311. {
  312.   FILE *infile, *outfile;
  313.   int count=0, c=0;
  314.   WORD bufSize, fileSize, value;
  315.   BYTE *bufferStart, *bufferCurrPt, *bp;
  316.   int thisisatest=0;
  317.   
  318.   if (strlen(InFileName)) {
  319.     if (!(infile = fopen(InFileName,FOPR))) {
  320.       fprintf(stderr, "bin2asc: unable to create %s\n",OutFileName);
  321.       exit(EXIT_FAILURE);
  322.     } 
  323.   }
  324.   else
  325.     infile = stdin;
  326.  
  327.   if (strlen(OutFileName)) {
  328.     if (!(outfile = fopen(OutFileName,FOPW))) {
  329.       fprintf(stderr, "bin2asc: unable to create %s\n",OutFileName);
  330.       exit(EXIT_FAILURE);
  331.     } 
  332.   }
  333.   else
  334.     outfile = stdout;
  335.   
  336.   fileSize = FileSize(infile);
  337.   if (fileSize > MAX_READ_SIZE*1024L) {
  338.     fprintf(stderr, "bin2asc: File %s is too long\n", InFileName);
  339.     exit(EXIT_FAILURE);
  340.   }
  341.   bufSize = 10+(WORD) (fileSize);  /* approximate byte size of object */
  342.   if (!(bufferStart = (BYTE *) malloc(bufSize))) {
  343.     fprintf(stderr, "bin2asc:  Unable to allocate %u bytes\n", bufSize);
  344.     exit(EXIT_FAILURE);
  345.   }
  346.   bufferCurrPt=bufferStart;
  347.  
  348.   fprintf(outfile,"%%%%HP: T(3)A(R)F(.);\n\"");
  349.   
  350.   for (count=8; count>0; count--)
  351.     c=getc(infile);
  352.  
  353.   while( (c=getc(infile)) != EOF )
  354.     (*(bufferCurrPt++))=c;
  355.   
  356.   value = crcBlock(bufferStart,(size_t)(bufferCurrPt-bufferStart)*2);
  357.  
  358.   *(bufferCurrPt++)=(value & 0x00ff);
  359.   *bufferCurrPt=((value & 0xff00) >> 8);
  360.     
  361.   while ((bp=bufferStart++) <= bufferCurrPt) {
  362.     
  363.     fprintf(outfile,"%1.1X%1.1X",(*bp & 0x0f),((*bp & 0xf0) >>4));
  364.     
  365.     if (! (++count % 32))
  366.       fprintf(outfile,"\n");
  367.   }
  368.  
  369.   thisisatest=1;
  370.  
  371.   fprintf(stderr,"CRC is #%Xh\n",value);
  372.   
  373.   fprintf(outfile,"\"\n");  
  374. }
  375.  
  376.  
  377. int main(argc, argv)
  378. int argc;
  379. char **argv;
  380. {
  381.     char filepath[FILENAME_MAX];
  382.     char b2aInFilePath[FILENAME_MAX], b2aOutFilePath[FILENAME_MAX];
  383.     BYTE *mb;
  384.     WORD objSize, rcrc, crc,bObjSize;  /*  NOTE: objSize is in nibbles! */
  385.  
  386.  
  387.     if (! strcmp(*argv,"asc2bin") ) 
  388.       {
  389.         if (argc < 2) {
  390.           fputs("usage:  asc2bin infile[.ext]\n", stderr);
  391.           fputs("\treads infile.ext and creates infile.bin\n", stderr);
  392.           fputs("\tif omitted, .ext is assumed to be .rpl\n", stderr);
  393.           exit(EXIT_FAILURE);
  394.         }
  395.  
  396.         strcpy(filepath, argv[1]);
  397.         
  398.         ReadFile(filepath, &mb, &objSize);
  399.         if (objSize < 2) {
  400.           fputs("asc2bin: String too short to include crc\n", stderr);
  401.           exit(EXIT_FAILURE);
  402.         }
  403.  
  404.         objSize -= 4;  /* nibbles */
  405.         bObjSize = objSize / 2 + (objSize & 1);
  406.         rcrc = (WORD) mb[bObjSize] + ((WORD) mb[bObjSize+1] << 8);
  407.  
  408.         crc = crcBlock(mb, objSize);
  409.         if (crc != rcrc) {
  410.           fprintf(stderr,
  411.           "asc2bin: Calculated CRC # %Xh does not match read CRC # %Xh\n",
  412.           crc, rcrc);
  413.           exit(EXIT_FAILURE);
  414.         }
  415.  
  416.         WriteFile(filepath, mb, bObjSize);
  417.  
  418.         return EXIT_SUCCESS;
  419.       }
  420.     else {
  421.       if ( argc < 1 )
  422.         b2aInFilePath[0] = '\0';
  423.       else
  424.         strcpy(b2aInFilePath, argv[1]);
  425.       if (argc < 2 )
  426.         b2aOutFilePath[0] = '\0';
  427.       else
  428.         strcpy(b2aOutFilePath, argv[2]);
  429.       
  430.       if (!TransBinFile(b2aInFilePath, b2aOutFilePath))
  431.         fprintf(stderr,"bin2asc: Tanslation to ASC format unsuccessful.\n");
  432.     }
  433.  
  434.   }
  435.  
  436.  
  437. /*--=--==--===--====--=====--======--======--=====--====--===--==--=--*
  438.  *                        END OF asc2bin.c                            *
  439.  *==-==--==---==----==-----==------==------==-----==----==---==--==-==*/
  440.  
  441.  
  442.